package eu.dominicum.ft.pd;

import eu.dominicum.ft.pd.mao.MakeFantasyTeamMemberMAO;
import eu.dominicum.ft.pd.mao.MakeParticipantMAO;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * A Participant is a person that plays the Fantasy Tour.
 *
 * @author Harry Klerks
 * @since 2013M1
 */
public class Participant extends PersistentDomainObject {

    /**
     * Pseudonym.
     */
    private String pseudonym;

    /**
     * Hide real name flag.
     */
    private Boolean hideRealName;

    /**
     * Person playing this role.
     */
    private Person person;

    /**
     * Has the entry fee been paid?
     */
    private Boolean paidEntryFee;

    /**
     * The associated {@link FantasyTour}.
     */
    private FantasyTour fantasyTour;

    /**
     * Protected constructor to satisfy JPA.
     */

    /**
     * The Participant's list of {@link FantasyTeamMember} objects.
     */
    private final List<FantasyTeamMember> fantasyTeamMembers = new ArrayList<>();

    /**
     * Protected constructor to satisfy JPA based persistence implementations.
     */
    protected Participant() {

    }

    /**
     * .
     *
     * @return String
     */
    public final String getPseudonym() {
        return pseudonym;
    }

    /**
     * .
     *
     * @return Boolean
     */
    public final Boolean getHideRealName() {
        return hideRealName;
    }

    /**
     * .
     *
     * @return Person
     */
    public final Person getPerson() {
        return person;
    }

    /**
     * .
     *
     * @return Boolean
     */
    public final Boolean getPaidEntryFee() {
        return paidEntryFee;
    }

    /**
     * .
     *
     * @return FantasyTour
     */
    public final FantasyTour getFantasyTour() {
        return fantasyTour;
    }

    /**
     * Makes a {@link Participant} object.
     *
     * @param makeParticipantMAO -
     * @return Participant
     */
    public static Participant make(final MakeParticipantMAO makeParticipantMAO) {

        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<MakeParticipantMAO>> violations = validator.validate(makeParticipantMAO);

        if (!violations.isEmpty()) {
            throw new ValidationException((violations.iterator().next().getMessage()));
        }

        Participant newParticipant = new Participant();

        newParticipant.pseudonym = makeParticipantMAO.getPseudonym();
        newParticipant.fantasyTour = makeParticipantMAO.getFantasyTour();
        newParticipant.hideRealName = makeParticipantMAO.getHideRealName();
        newParticipant.paidEntryFee = makeParticipantMAO.getPaidEntryFee();

        if (makeParticipantMAO.getPersonId() == 0L) {
            newParticipant.person = Person.make(makeParticipantMAO.getMakePersonMAO());
        } else {
            newParticipant.person = makeParticipantMAO.getPerson();
        }

        Integer ridersInListCount = makeParticipantMAO.getFantasyTour().getConfiguration().getRidersInListCount();
        Integer substitutesInListCount = makeParticipantMAO.getFantasyTour().getConfiguration().getSubstitutesInListCount();
        MakeFantasyTeamMemberMAO makeFantasyTeamMemberMAO;
        for (int rank = 1; rank <= ridersInListCount; rank++) {
            makeFantasyTeamMemberMAO = new MakeFantasyTeamMemberMAO();
            makeFantasyTeamMemberMAO.setRank(rank);
            makeFantasyTeamMemberMAO.setParticipant(newParticipant);
            makeFantasyTeamMemberMAO.setSubstitute(Boolean.FALSE);
            FantasyTeamMember newFantasyTeamMember = FantasyTeamMember.make(makeFantasyTeamMemberMAO);
            newParticipant.addToFantasyTeamMembers(newFantasyTeamMember);
        }
        for (int rank = 1; rank <= substitutesInListCount; rank++) {
            makeFantasyTeamMemberMAO = new MakeFantasyTeamMemberMAO();
            makeFantasyTeamMemberMAO.setRank(rank);
            makeFantasyTeamMemberMAO.setParticipant(newParticipant);
            makeFantasyTeamMemberMAO.setSubstitute(Boolean.TRUE);
            FantasyTeamMember newFantasyTeamMember = FantasyTeamMember.make(makeFantasyTeamMemberMAO);
            newParticipant.addToFantasyTeamMembers(newFantasyTeamMember);
        }

        return newParticipant;
    }

    /**
     * Add a {@link FantasyTeamMember} object to the list of associated objects.
     *
     * @param newFantasyTeamMember -
     */
    private void addToFantasyTeamMembers(final FantasyTeamMember newFantasyTeamMember) {

        this.fantasyTeamMembers.add(newFantasyTeamMember);
    }

    /**
     * .
     *
     * @return List <FantasyTeamMember>
     */
    public final List<FantasyTeamMember> getFantasyTeamMembers() {
        return fantasyTeamMembers;
    }

    /**
     * Reveal the Participant's real name.
     */
    final void revealRealName() {

        this.hideRealName = Boolean.FALSE;
    }
}
